﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Rachmans.Sabang.Model;
using Rachmans.Sabang.Tools;
using Microsoft.Phone.Shell;

namespace Rachmans.Sabang
{
    enum ShowQuranMode
    {
        none
            , init 
        , page
        , sura
        , juz
    }

    public partial class NewQuran : PhoneApplicationPage, INotifyPropertyChanged
    {
        // Data context for the local database
        private BookmarkContext bookmarkDB;

        // Define an observable collection property that controls can bind to.
        private ObservableCollection<Bookmark> _bookmarks;
        public ObservableCollection<Bookmark> Bookmarks
        {
            get
            {
                return _bookmarks;
            }
            set
            {
                if (_bookmarks != value)
                {
                    _bookmarks = value;
                    NotifyPropertyChanged("Bookmarks");
                }
            }
        }

        int _requestedPageNumber = Constant.START_PAGE;
        DataSourceLoader _dsLoader = new DataSourceLoader();
        TranslationLoader _tLoader;
        ShowQuranMode _mode = ShowQuranMode.init;
        Bookmark _bookmark = (Application.Current as App).Bookmark;
        string _translation = (Application.Current as App).Translation;

        public NewQuran()
        {
            InitializeComponent();
            border.Visibility = System.Windows.Visibility.Collapsed;
            borderConfirmation.Visibility = System.Windows.Visibility.Collapsed;
            _mode = ShowQuranMode.init;

            _dsLoader.LoadDictionaries();

            //  Load Translation.
            foreach (string key in _dsLoader.Translations.Keys)
            {
                lpTranslation.Items.Add(key);
            }


            loadJuzs();
            loadSuras();

            _mode = ShowQuranMode.none;

            if (_bookmark != null)
            {
                //  Get the latest page saved in bookmarks.
                _requestedPageNumber = _bookmark.Page;
                _mode = ShowQuranMode.page;
            }

            // Connect to the database and instantiate data context.
            bookmarkDB = new BookmarkContext(BookmarkContext.DBConnectionString);

            // Data context and observable collection are children of the main page.
            this.DataContext = this;

            // Define the query to gather all of the to-do items.
            var bookmarksInDB = from Bookmark bookmark in bookmarkDB.Bookmarks
                                select bookmark;

            // Execute the query and place the results into a collection.
            Bookmarks = new ObservableCollection<Bookmark>(bookmarksInDB);

            PhoneApplicationService.Current.UserIdleDetectionMode = IdleDetectionMode.Disabled;
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        /// <summary>
        /// On navigated to Quran, this page is expecting Quran's Page parameter.
        /// </summary>
        /// <param name="e"></param>
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            //_mode = ShowQuranMode.init;
            IDictionary<string, string> parameters = this.NavigationContext.QueryString;

            if (parameters.ContainsKey(Constant.PAGE))
            {
                if (!Int32.TryParse(parameters[Constant.PAGE], out _requestedPageNumber))
                {
                    _requestedPageNumber = Constant.START_PAGE;
                }
            }

            base.OnNavigatedTo(e);
            this.NavigationContext.QueryString.Clear();

            if (!_dsLoader.Pages.ContainsKey(_requestedPageNumber))
            {
                _dsLoader.LoadPage(_requestedPageNumber);
            }

            loadPage();
        }

        private void loadSuras()
        {
            _dsLoader.LoadSuras();
            foreach (string key in _dsLoader.Suras.Keys)
            {
                lpSura.Items.Add(new StringBuilder(ArabicCharacterHelper.GetArabicNumber(Int32.Parse(_dsLoader.Suras[key].index), _dsLoader.Numbers)).Append(" - سورة").Append(_dsLoader.Suras[key].name));
            }
        }

        private void loadJuzs()
        {
            _dsLoader.LoadJuzs();
            foreach (string key in _dsLoader.Juzs.Keys)
            {
                lpJuz.Items.Add(new StringBuilder(ArabicCharacterHelper.GetArabicNumber(Int32.Parse(_dsLoader.Juzs[key].index), _dsLoader.Numbers)).Append(" - الجزء").Append(_dsLoader.Juzs[key].words).ToString());
            }
        }

        private void loadPage()
        {
            if (Aya != null)
            {
                _isRenderingPage = true;

                Aya.FontSize = _fontSize;
                Aya.FlowDirection = FlowDirection.RightToLeft;
                this.Aya.Text = string.Empty;
                Aya.FontFamily = new System.Windows.Media.FontFamily("/Fonts/me_quran_volt_newmet.ttf#me_quran");

                //  Load selected Quran's page.
                quranPagesPage quranPage = _dsLoader.Pages[_requestedPageNumber];

                //  Set start and end of sura index.
                int startSuraIndex = Int32.Parse(quranPage.sura);
                int endSuraIndex = 0;

                //  If selected page is not last page then load next page information.
                quranPagesPage nextQuranPage = null;
                if (_requestedPageNumber < Constant.MAX_PAGE)
                {
                    nextQuranPage = _dsLoader.Pages[_requestedPageNumber + 1];
                    if (Int32.Parse(nextQuranPage.aya) > 1)
                    {
                        endSuraIndex = Int32.Parse(nextQuranPage.sura);
                    }
                    else
                    {
                        endSuraIndex = Int32.Parse(nextQuranPage.sura) - 1;
                    }
                }
                else
                {
                    endSuraIndex = Constant.MAX_SURA;// +1;
                }

                //  Set start sura and end sura.
                List<quranSurasSura> selectedSuras = new List<quranSurasSura>();

                if (endSuraIndex > startSuraIndex)
                {
                    for (int i = startSuraIndex; i <= endSuraIndex; i++)
                    {
                        selectedSuras.Add(_dsLoader.Suras[i.ToString()]);
                    }
                }
                else
                {
                    selectedSuras.Add(_dsLoader.Suras[startSuraIndex.ToString()]);
                }

                //  Get ayas from the first sura.
                int startAyaIndex = Int32.Parse(quranPage.aya);
                int endAyaIndex;

                if (selectedSuras.Count > 1)
                {
                    //  End aya index is the last aya.
                    if (nextQuranPage != null)
                    {
                        //  Check if next quran page is the same sura.
                        if (quranPage.sura == nextQuranPage.sura)
                        {
                            endAyaIndex = Int32.Parse(nextQuranPage.aya) - 1;
                        }
                        else
                        {
                            //  End aya index is the last aya.
                            endAyaIndex = Int32.Parse(selectedSuras[0].ayas);
                        }
                    }
                    else
                    {
                        //  End aya index is the last aya.
                        endAyaIndex = Int32.Parse(selectedSuras[0].ayas);
                    }
                }
                else
                {
                    if (nextQuranPage != null)
                    {
                        //  Check if next quran page is the same sura.
                        if (quranPage.sura == nextQuranPage.sura)
                        {
                            endAyaIndex = Int32.Parse(nextQuranPage.aya) - 1;
                        }
                        else
                        {
                            //  End aya index is the last aya.
                            endAyaIndex = Int32.Parse(selectedSuras[0].ayas);
                        }
                    }
                    else
                    {
                        //  End aya index is the last aya.
                        endAyaIndex = Int32.Parse(selectedSuras[0].ayas);
                    }
                }

                StringBuilder sbQuran = new StringBuilder();

                if (!_dsLoader.Quran.Keys.Contains(quranPage.sura))
                {
                    //  Load first the sura's aya.
                    _dsLoader.LoadQuran(Int32.Parse(quranPage.sura));
                }

                quranSura qSura = _dsLoader.Quran[quranPage.sura];
                for (int i = startAyaIndex - 1; i < endAyaIndex; i++)
                {
                    if (!string.IsNullOrEmpty(qSura.aya[i].bismillah))
                    {
                        sbQuran.Append(qSura.aya[i].bismillah).Append("\n");
                    }
                    sbQuran.Append(qSura.aya[i].text).Append(" (").Append(ArabicCharacterHelper.GetArabicNumber(i + 1, _dsLoader.Numbers)).Append(") ");
                }

                //  Process for the next sura.
                for (int i = 1; i < selectedSuras.Count; i++)
                {
                    //  The start index will ALWAYS be 1.
                    startAyaIndex = 1;

                    if (i < selectedSuras.Count)
                    {
                        //  End aya index is the last aya.
                        if (nextQuranPage != null)
                        {
                            //  Check if next quran page is the same sura.
                            if (selectedSuras[i].index == nextQuranPage.sura)
                            {
                                endAyaIndex = Int32.Parse(nextQuranPage.aya) - 1;
                            }
                            else
                            {
                                //  End aya index is the last aya.
                                endAyaIndex = Int32.Parse(selectedSuras[i].ayas);
                            }
                        }
                        else
                        {
                            //  End aya index is the last aya.
                            endAyaIndex = Int32.Parse(selectedSuras[i].ayas);
                        }
                    }
                    else
                    {
                        if (nextQuranPage != null)
                        {
                            //  Check if next quran page is the same sura.
                            if (selectedSuras[i].index == nextQuranPage.sura)
                            {
                                endAyaIndex = Int32.Parse(nextQuranPage.aya) - 1;
                            }
                            else
                            {
                                //  End aya index is the last aya.
                                endAyaIndex = Int32.Parse(selectedSuras[i].ayas);
                            }
                        }
                        else
                        {
                            //  End aya index is the last aya.
                            endAyaIndex = Int32.Parse(selectedSuras[i].ayas);
                        }
                    }

                    sbQuran.Append("\n");

                    if (!_dsLoader.Quran.Keys.Contains(selectedSuras[i].index))
                    {
                        //  Load first the sura's aya.
                        _dsLoader.LoadQuran(Int32.Parse(selectedSuras[i].index));
                    }

                    qSura = _dsLoader.Quran[selectedSuras[i].index];
                    for (int j = startAyaIndex - 1; j < endAyaIndex; j++)
                    {
                        if (!string.IsNullOrEmpty(qSura.aya[j].bismillah))
                        {
                            sbQuran.Append(qSura.aya[j].bismillah).Append("\n");
                        }
                        sbQuran.Append(qSura.aya[j].text).Append(" (").Append(ArabicCharacterHelper.GetArabicNumber(j + 1, _dsLoader.Numbers)).Append(") ");
                    }


                }

                //  Load first sura if loaded by page.
                _shownSura = Int32.Parse(selectedSuras[selectedSuras.Count - 1].index);

                this.Aya.Text = sbQuran.ToString();

                //  Update list of active sura.
                if (lpSura.Items.Count > 0)
                {
                    lpSura.SelectedIndex = _shownSura - 1;
                    tbSura.Text = (lpSura.Items[lpSura.SelectedIndex] as StringBuilder).ToString();
                }

                sldPage.Value = _requestedPageNumber;
                txtPage.Text = _requestedPageNumber.ToString();
                tbPageMin.Text = ArabicCharacterHelper.GetArabicNumber(_requestedPageNumber, _dsLoader.Numbers);

                if (lpJuz.Items.Count > 0)
                {
                    lpJuz.SelectedIndex = getJuzFromPage(_requestedPageNumber) - 1;
                    tbJuz.Text = lpJuz.Items[lpJuz.SelectedIndex] as string;
                }

                //  Save to bookmarks.
                saveBookmark();

                //  Set to top.
                sv.ScrollToVerticalOffset(0);

                _isRenderingPage = false;
            }
        }

        private void saveBookmark()
        {
            if (_bookmark != null)
            {
                _bookmark.DtmSave = DateTime.Now;
                _bookmark.Page = _requestedPageNumber;
            }
            else
            {
                _bookmark = new Bookmark { DtmSave = DateTime.Now, Page = _requestedPageNumber };
            }
        }

        private int _shownSura = 1;

        private void loadTranslation()
        {
            _isRenderingPage = true;

            if (_translation == null)
            {
                _translation = lpTranslation.Items[0].ToString();
            }
            Aya.FontSize = _fontSize;

            //  Set translation based on selected one.
            switch (_dsLoader.Translations[_translation].FlowDirection)
            {
                case "LTR":
                    Aya.FlowDirection = FlowDirection.LeftToRight;
                    break;
                case "RTL":
                    Aya.FlowDirection = FlowDirection.RightToLeft;
                    break;
            }

            if (!string.IsNullOrEmpty(_dsLoader.Translations[_translation].Font))
            {
                Aya.FontFamily = new System.Windows.Media.FontFamily(string.Format("/Fonts/{0}", _dsLoader.Translations[_translation].Font));
            }
            else
            {
                Aya.FontFamily = new System.Windows.Media.FontFamily("Calibri");
            }

            //  Show tranlation here.
            if (_tLoader == null || _tLoader.Translation.ToLower() != _translation)
            {
                _tLoader = new TranslationLoader(ref _dsLoader, _dsLoader.Translations[_translation].Text, _dsLoader.Translations[_translation].Language);
            }

            this.Aya.Text = string.Empty;
            tbPageMin.Text = _requestedPageNumber.ToString();

            //  Load selected Quran's page.
            quranPagesPage quranPage = _dsLoader.Pages[_requestedPageNumber];

            //  Set start and end of sura index.
            int startSuraIndex = Int32.Parse(quranPage.sura);
            int endSuraIndex = 0;

            //  If selected page is not last page then load next page information.
            quranPagesPage nextQuranPage = null;
            if (_requestedPageNumber < Constant.MAX_PAGE)
            {
                nextQuranPage = _dsLoader.Pages[_requestedPageNumber + 1];
                if (Int32.Parse(nextQuranPage.aya) > 1)
                {
                    endSuraIndex = Int32.Parse(nextQuranPage.sura);
                }
                else
                {
                    endSuraIndex = Int32.Parse(nextQuranPage.sura) - 1;
                }
            }
            else
            {
                endSuraIndex = Constant.MAX_SURA;// +1;
            }

            //  Set start sura and end sura.
            List<quranSurasSura> selectedSuras = new List<quranSurasSura>();

            if (endSuraIndex > startSuraIndex)
            {
                for (int i = startSuraIndex; i <= endSuraIndex; i++)
                {
                    selectedSuras.Add(_dsLoader.Suras[i.ToString()]);
                }
            }
            else
            {
                selectedSuras.Add(_dsLoader.Suras[startSuraIndex.ToString()]);
            }

            //  Get ayas from the first sura.
            int startAyaIndex = Int32.Parse(quranPage.aya);
            int endAyaIndex;

            if (selectedSuras.Count > 1)
            {
                //  End aya index is the last aya.
                if (nextQuranPage != null)
                {
                    //  Check if next quran page is the same sura.
                    if (quranPage.sura == nextQuranPage.sura)
                    {
                        endAyaIndex = Int32.Parse(nextQuranPage.aya) - 1;
                    }
                    else
                    {
                        //  End aya index is the last aya.
                        endAyaIndex = Int32.Parse(selectedSuras[0].ayas);
                    }
                }
                else
                {
                    //  End aya index is the last aya.
                    endAyaIndex = Int32.Parse(selectedSuras[0].ayas);
                }
            }
            else
            {
                if (nextQuranPage != null)
                {
                    //  Check if next quran page is the same sura.
                    if (quranPage.sura == nextQuranPage.sura)
                    {
                        endAyaIndex = Int32.Parse(nextQuranPage.aya) - 1;
                    }
                    else
                    {
                        //  End aya index is the last aya.
                        endAyaIndex = Int32.Parse(selectedSuras[0].ayas);
                    }
                }
                else
                {
                    //  End aya index is the last aya.
                    endAyaIndex = Int32.Parse(selectedSuras[0].ayas);
                }
            }

            StringBuilder sbQuran = new StringBuilder();
            if (!_dsLoader.Quran.Keys.Contains(quranPage.sura))
            {
                //  Load first the sura's aya.
                _dsLoader.LoadQuran(Int32.Parse(quranPage.sura));
            }
            quranSura qSura = _dsLoader.Quran[quranPage.sura];
            for (int i = startAyaIndex - 1; i < endAyaIndex; i++)
            {
                if (!string.IsNullOrEmpty(qSura.aya[i].bismillah))
                {
                    //sbQuran.Append(qSura.aya[i].bismillah).Append("\n");
                    sbQuran.Append(_tLoader.DictTranslations["1"][1]).Append("\n");
                }
                sbQuran.Append(_tLoader.DictTranslations[quranPage.sura][i + 1]).Append(" (").Append(i + 1).Append(") ");
            }

            //  Process for the next sura.
            for (int i = 1; i < selectedSuras.Count; i++)
            {
                //  The start index will ALWAYS be 1.
                startAyaIndex = 1;

                if (i < selectedSuras.Count)
                {
                    //  End aya index is the last aya.
                    if (nextQuranPage != null)
                    {
                        //  Check if next quran page is the same sura.
                        if (selectedSuras[i].index == nextQuranPage.sura)
                        {
                            endAyaIndex = Int32.Parse(nextQuranPage.aya) - 1;
                        }
                        else
                        {
                            //  End aya index is the last aya.
                            endAyaIndex = Int32.Parse(selectedSuras[i].ayas);
                        }
                    }
                    else
                    {
                        //  End aya index is the last aya.
                        endAyaIndex = Int32.Parse(selectedSuras[i].ayas);
                    }
                }
                else
                {
                    if (nextQuranPage != null)
                    {
                        //  Check if next quran page is the same sura.
                        if (selectedSuras[i].index == nextQuranPage.sura)
                        {
                            endAyaIndex = Int32.Parse(nextQuranPage.aya) - 1;
                        }
                        else
                        {
                            //  End aya index is the last aya.
                            endAyaIndex = Int32.Parse(selectedSuras[i].ayas);
                        }
                    }
                    else
                    {
                        //  End aya index is the last aya.
                        endAyaIndex = Int32.Parse(selectedSuras[i].ayas);
                    }
                }

                sbQuran.Append("\n");
                if (!_dsLoader.Quran.Keys.Contains(selectedSuras[i].index))
                {
                    //  Load first the sura's aya.
                    _dsLoader.LoadQuran(Int32.Parse(selectedSuras[i].index));
                }
                qSura = _dsLoader.Quran[selectedSuras[i].index];
                for (int j = startAyaIndex - 1; j < endAyaIndex; j++)
                {
                    if (!string.IsNullOrEmpty(qSura.aya[j].bismillah))
                    {
                        //sbQuran.Append(qSura.aya[j].bismillah).Append("\n");
                        sbQuran.Append(_tLoader.DictTranslations["1"][1]).Append("\n");
                    }
                    sbQuran.Append(_tLoader.DictTranslations[selectedSuras[i].index][j + 1]).Append(" (").Append(j + 1).Append(") ");
                }
            }

            //  Load first sura if loaded by page.
            _shownSura = Int32.Parse(selectedSuras[selectedSuras.Count - 1].index);
            this.Aya.Text = sbQuran.ToString();

            //  Update list of active sura.
            if (lpSura.Items.Count > 0)
            {
                lpSura.SelectedIndex = _shownSura - 1;
                tbSura.Text = (lpSura.Items[lpSura.SelectedIndex] as StringBuilder).ToString();
            }

            sldPage.Value = _requestedPageNumber;
            txtPage.Text = _requestedPageNumber.ToString();

            if (lpJuz.Items.Count > 0)
            {
                lpJuz.SelectedIndex = getJuzFromPage(_requestedPageNumber) - 1;
                tbJuz.Text = lpJuz.Items[lpJuz.SelectedIndex] as string;
            }

            //  Save to bookmarks.
            saveBookmark();

            //  Set to top.
            sv.ScrollToVerticalOffset(0);

            _isRenderingPage = false;
        }

        bool _isShowTranslation = false;

        private void Aya_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
        {
            DateTime dtmStop = DateTime.Now;
            TimeSpan span = dtmStop - _dtmStart;

            if (borderConfirmation.Visibility == System.Windows.Visibility.Visible)
            {
                borderConfirmation.Visibility = System.Windows.Visibility.Collapsed;
            }
            else if (border.Visibility == System.Windows.Visibility.Visible)
            {
                border.Visibility = System.Windows.Visibility.Collapsed;
            }
            else
            {
                if (span.TotalSeconds > 0.5)
                {
                    //  Options.
                    //this.NavigationService.Navigate(new Uri("/QuranNavigator.xaml", UriKind.Relative));
                    //border.Visibility = System.Windows.Visibility.Visible;
                }
                else
                {
                    //  If tap: Options.

                    _mode = ShowQuranMode.page;
                    if (e.TotalManipulation.Translation.X == 0 && e.TotalManipulation.Translation.Y == 0)
                    {
                        if (grdHeader.Visibility == System.Windows.Visibility.Visible)
                        {
                            grdHeader.Visibility = System.Windows.Visibility.Collapsed;
                            grdSlider.Visibility = System.Windows.Visibility.Collapsed;
                            grdPage.Visibility = System.Windows.Visibility.Visible;
                            ApplicationBar.IsVisible = false;
                            grdDefaultHeader.Visibility = System.Windows.Visibility.Visible;
                        }
                        else
                        {
                            grdDefaultHeader.Visibility = System.Windows.Visibility.Collapsed;
                            grdHeader.Visibility = System.Windows.Visibility.Visible;
                            grdPage.Visibility = System.Windows.Visibility.Collapsed;
                            grdSlider.Visibility = System.Windows.Visibility.Visible;

                            //if (Orientation == PageOrientation.Portrait || Orientation == PageOrientation.PortraitDown || Orientation == PageOrientation.PortraitUp)
                            //{
                                ApplicationBar.IsVisible = true;
                            //}
                        }
                        //if (!_isShowTranslation)
                        //{
                        //    loadTranslation();
                        //    _isShowTranslation = true;
                        //}
                        //else
                        //{
                        //    loadPage();
                        //    _isShowTranslation = false;
                        //}
                    }
                    else
                    {
                        //  This is a tolerance value to move right and left. 
                        //  Since we don't want to change the page if user move UP and DOWN (assumption that the Y value will be GT 100).
                        if (Math.Abs(e.TotalManipulation.Translation.Y) < 100)
                        {
                            // In Landscape orientation the tolerance for up and down will be using X factor with value 300.
                            if (((Orientation == PageOrientation.Landscape || Orientation == PageOrientation.LandscapeLeft
                                || Orientation == PageOrientation.LandscapeRight) && Math.Abs(e.TotalManipulation.Translation.X) > 300) 
                                || (Orientation == PageOrientation.Portrait || Orientation == PageOrientation.PortraitDown 
                                || Orientation == PageOrientation.PortraitUp))
                            {

                                //  If touch goes right then next page.
                                if (e.TotalManipulation.Translation.X > 0)
                                {
                                    if (_requestedPageNumber < Constant.MAX_PAGE)
                                    {
                                        _requestedPageNumber++;
                                    }
                                    else
                                    {
                                        _requestedPageNumber = Constant.START_PAGE;
                                    }
                                }
                                else if (e.TotalManipulation.Translation.X < 0)
                                {
                                    if (_requestedPageNumber > Constant.START_PAGE)
                                    {
                                        _requestedPageNumber--;
                                    }
                                    else
                                    {
                                        _requestedPageNumber = Constant.MAX_PAGE;
                                    }
                                }

                                if (!_dsLoader.Pages.ContainsKey(_requestedPageNumber) || !_dsLoader.Pages.ContainsKey(_requestedPageNumber + 1))
                                {
                                    _dsLoader.LoadPage(_requestedPageNumber);
                                }

                                if (!_isShowTranslation)
                                {
                                    loadPage();
                                }
                                else
                                {
                                    loadTranslation();
                                }
                            }
                        }
                    }

                    _mode = ShowQuranMode.none;
                }
            }
        }

        DateTime _dtmStart;

        private void Aya_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
        {
            _dtmStart = DateTime.Now;
        }

        private void loadSura(int suraNumber)
        {
            if (_dsLoader.Pages.Count > 0)
            {
                //  Get the sura number.
                quranPagesPage page = _dsLoader.Pages.Values.Where(v => Int32.Parse(v.sura) == suraNumber && Int32.Parse(v.aya) == 1).OrderBy(v => Int32.Parse(v.sura)).FirstOrDefault();

                if (page != null)
                {
                    if (Int32.Parse(page.aya) == 1)
                    {
                        _requestedPageNumber = Int32.Parse(page.index);
                    }
                    else
                    {
                        _requestedPageNumber = Int32.Parse(page.index) - 1;
                    }


                    if (!_dsLoader.Pages.ContainsKey(_requestedPageNumber) || !_dsLoader.Pages.ContainsKey(_requestedPageNumber + 1))
                    {
                        _dsLoader.LoadPage(_requestedPageNumber);
                    }
                }
                else
                {
                    //  Load Sura.
                    _requestedPageNumber = _dsLoader.LoadSuraStartPage(suraNumber);
                }

                loadPage();
            }
        }

        private void loadJuz(int juzNumber)
        {
            if (_dsLoader.Pages.Count > 0)
            {
                //  Get the juz information.
                quranJuzsJuz juz = _dsLoader.Juzs.Values.Where(j => Int32.Parse(j.index) == juzNumber).FirstOrDefault();

                if (juz != null)
                {
                    quranPagesPage pg = _dsLoader.Pages.Values.Where(p => Int32.Parse(p.sura) == Int32.Parse(juz.sura) && (Int32.Parse(p.aya) == Int32.Parse(juz.aya))).FirstOrDefault();

                    if (pg == null)
                    {
                            _dsLoader.LoadPagesUntil(Int32.Parse(juz.sura), Int32.Parse(juz.aya));
                            pg = _dsLoader.Pages.Values.Where(p => Int32.Parse(p.sura) == Int32.Parse(juz.sura) && (Int32.Parse(p.aya) == Int32.Parse(juz.aya))).FirstOrDefault();

                            if (pg == null)
                            {
                                pg = _dsLoader.Pages.Values.Where(p => Int32.Parse(p.sura) == Int32.Parse(juz.sura) && ((Int32.Parse(p.aya) < Int32.Parse(juz.aya)))).LastOrDefault();

                                if (pg == null)
                                {
                                    pg = _dsLoader.Pages.Values.Where(p => Int32.Parse(p.sura) == Int32.Parse(juz.sura) - 1).LastOrDefault();
                                }
                            }
                    }

                    if (pg != null)
                    {
                        //  Load all pages between selected page and juz's page.

                        _requestedPageNumber = Int32.Parse(pg.index);

                        if (!_dsLoader.Pages.ContainsKey(_requestedPageNumber) || !_dsLoader.Pages.ContainsKey(_requestedPageNumber + 1))
                        {
                            _dsLoader.LoadPage(_requestedPageNumber);
                        }
                    }
                    else
                    {
                        //  Load Sura.
                        _requestedPageNumber = _dsLoader.LoadSuraStartPage(juzNumber);
                    }

                    loadPage();
                }

            }
        }

        private void redSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            _shownSura = (int)Math.Round(e.NewValue);
            loadSura(_shownSura);
        }

        private void btnPlus_Click(object sender, RoutedEventArgs e)
        {
            if (_shownSura < Constant.MAX_SURA)
            {
                _shownSura++;
            }
            else
            {
                _shownSura = 1;
            }

            loadSura(_shownSura);
        }

        private void btnMin_Click(object sender, RoutedEventArgs e)
        {
            if (_shownSura > 1)
            {
                _shownSura--;
            }
            else
            {
                _shownSura = Constant.MAX_SURA;
            }

            loadSura(_shownSura);
        }

        private void lpSura_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
        {
            if (e.AddedItems.Count > 0 && (_mode == ShowQuranMode.none || _mode == ShowQuranMode.sura) && !_isRenderingPage)
            {
                _mode = ShowQuranMode.sura;
                int sura = (sender as ListPicker).SelectedIndex + 1;
                if (sura >= Constant.MIN_SURA && sura <= Constant.MAX_SURA)
                {
                    _shownSura = sura;
                }

                loadSura(_shownSura);

                _mode = ShowQuranMode.none;
            }
        }

        private void loadPage(int requestedPageNumber)
        {
            if (requestedPageNumber < 1)
            {
                _requestedPageNumber = Constant.MAX_PAGE;
            }
            else if (requestedPageNumber > Constant.MAX_PAGE)
            {
                _requestedPageNumber = 1;
            }
            else
            {
                _requestedPageNumber = requestedPageNumber;
            }

            if (!_dsLoader.Pages.ContainsKey(_requestedPageNumber) || !_dsLoader.Pages.ContainsKey(_requestedPageNumber + 1))
            {
                _dsLoader.LoadPage(_requestedPageNumber);
            }

            if (!_isShowTranslation)
            {
                loadPage();
            }
            else
            {
                loadTranslation();
            }
        }

        private bool _isRenderingPage = false;

        private void pageSlide_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            if ((_mode == ShowQuranMode.none || _mode == ShowQuranMode.page) && !_isRenderingPage)
            {
                int requestedPageNumber = (int)Math.Round(e.NewValue);
                loadPage(requestedPageNumber);
                _mode = ShowQuranMode.none;
            }
        }

        private int _shownJuz = 1;
        
        private void lpJuz_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (e.AddedItems.Count > 0 && (_mode == ShowQuranMode.none || _mode == ShowQuranMode.juz) && !_isRenderingPage)
            {
                _mode = ShowQuranMode.juz;

                int juz = (sender as ListPicker).SelectedIndex + 1;
                if (juz >= Constant.MIN_JUZ && juz <= Constant.MAX_JUZ)
                {
                    _shownJuz = juz;
                }

                loadJuz(_shownJuz);

                _mode = ShowQuranMode.none;
            }
        }

        private int getJuzFromPage(int page)
        {
            //  Get page sura and aya.
            if (!_dsLoader.Pages.ContainsKey(page))
            {
                _dsLoader.LoadPage(page);
            }

            quranPagesPage pg = _dsLoader.Pages[page];
            int pgSura = Int32.Parse(pg.sura);
            int pgAya = Int32.Parse(pg.aya);

            //1. Find the juz which has same sura and aya.
            quranJuzsJuz juz = _dsLoader.Juzs.Values.Where(j => Int32.Parse(j.sura) == pgSura && Int32.Parse(j.aya) == pgAya).FirstOrDefault();

            if (juz != null)
            {
                return Int32.Parse(juz.index);
            }
            else
            {
                //  2. Find the juz with the same sura BUT differen aya (even it would be good if we can get directly the aya is GREATER than the page aya.
                juz = _dsLoader.Juzs.Values.Where(j => Int32.Parse(j.sura) == pgSura && Int32.Parse(j.aya) > pgAya).FirstOrDefault();

                if (juz != null)
                {
                    return Int32.Parse(juz.index) - 1;
                }
                else
                {
                    // 3. Find the juz that has sura GREATER THAN page sura.
                    juz = _dsLoader.Juzs.Values.Where(j => Int32.Parse(j.sura) > pgSura).FirstOrDefault();

                    if (juz != null)
                    {
                        return Int32.Parse(juz.index) - 1;
                    }
                    else
                    {
                        return Constant.MAX_JUZ;
                    }
                }
            }
        }

        private void PhoneApplicationPage_Unloaded(object sender, RoutedEventArgs e)
        {
            (Application.Current as App).Bookmark = _bookmark;
            (Application.Current as App).Translation = _translation;
        }

        private void btnSave_Click(object sender, RoutedEventArgs e)
        {
            _translation = lpTranslation.SelectedItem.ToString();
            border.Visibility = System.Windows.Visibility.Collapsed;

            if (_isShowTranslation)
            {
                loadTranslation();
            }
        }

        private void btnSaveBookmark_Click(object sender, RoutedEventArgs e)
        {
            Bookmark b = new Bookmark { DtmSave = DateTime.Now, Page = _requestedPageNumber };
            Bookmarks.Add(b);
            bookmarkDB.Bookmarks.InsertOnSubmit(b);
            bookmarkDB.SubmitChanges();

            borderConfirmation.Visibility = System.Windows.Visibility.Collapsed;
        }

        private void btnShowBookmarks_Click(object sender, RoutedEventArgs e)
        {
            borderConfirmation.Visibility = System.Windows.Visibility.Collapsed;
            this.NavigationService.Navigate(new Uri("/UI/Quran/MultiselectListSample.xaml", UriKind.Relative));
        }

        private void tbPageMin_Tap(object sender, System.Windows.Input.GestureEventArgs e)
        {
            grdSlider.Visibility = System.Windows.Visibility.Visible;
        }

        private void tbPage_Tap(object sender, System.Windows.Input.GestureEventArgs e)
        {
            grdSlider.Visibility = System.Windows.Visibility.Collapsed;
        }

        private void ApplicationBarMenuItem_Click(object sender, EventArgs e)
        {
            borderConfirmation.Visibility = System.Windows.Visibility.Visible;
        }

        private void ApplicationBarMenuItem_Click_1(object sender, EventArgs e)
        {
            border.Visibility = System.Windows.Visibility.Visible;
        }

        private void ApplicationBarMenuItem_Click_2(object sender, EventArgs e)
        {
            if (!_isShowTranslation)
            {
                loadTranslation();
                _isShowTranslation = true;
            }
            else
            {
                loadPage();
                _isShowTranslation = false;
            }
        }

        private int _fontSize = 25;

        private void PhoneApplicationPage_OrientationChanged(object sender, OrientationChangedEventArgs e)
        {
            if (e.Orientation == PageOrientation.LandscapeLeft || e.Orientation == PageOrientation.Landscape || e.Orientation == PageOrientation.LandscapeRight)
            {
                Aya.FontSize = _fontSize = 35;
            }
            else
            {
                Aya.FontSize = _fontSize = 25;
            }
        }

        private void ApplicationBarIconButton_Click(object sender, EventArgs e)
        {
            this.NavigationService.Navigate(new Uri("/UI/Quran/Licenses.xaml", UriKind.Relative));
        }

        private void btnJump_Click(object sender, RoutedEventArgs e)
        {
            int requestedPageNumber = _requestedPageNumber;
            if (int.TryParse(txtPage.Text, out requestedPageNumber))
            {
                loadPage(requestedPageNumber);
            }
            else
            {
                txtPage.Text = _requestedPageNumber.ToString();
            }
        }
    }
}